home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / C⁄C++ / graph3D / graph3D source / g3D_EvalFunc.c < prev    next >
Text File  |  1993-09-17  |  14KB  |  795 lines

  1. /*
  2.     Copyright '89    Christopher Moll
  3.     all rights reserved
  4. */
  5.  
  6.  
  7. #include    "graph3D.h"
  8.  
  9. #ifdef    _LSC3_
  10. #    include    <QuickDraw.h>
  11. #    include    <TextEdit.h>
  12. #    include    <EventMgr.h>
  13. #    include    <DialogMgr.h>
  14. #    include    <MemoryMgr.h>
  15. #endif
  16.  
  17.  
  18. extern    DialogPtr        functDial;
  19.  
  20. extern    Boolean    useMainFunc;
  21.  
  22. extern    int        mainFunct[64];
  23. extern    int        numMnOps;
  24. extern    Real    mnConsts[30];
  25. extern    int        numMnConsts;
  26.  
  27. extern    int        derivFunct[64];
  28. extern    int        numDerivOps;
  29. extern    Real    derivConsts[30];
  30. extern    int        numDerivConsts;
  31.  
  32. extern    Real        *funcResults;
  33. extern    Vector        *scalVectResults;
  34. extern    Point        *graphPoints;    /* same elements as funcResults */
  35.  
  36. extern    Real    startX, startY;
  37. extern    Real    endX, endY;
  38. extern    Real    deltaX, deltaY;
  39. extern    int        numX, numY;
  40.  
  41. extern    Boolean        functCurrent;
  42. extern    Boolean        vectrsCurrent;
  43.  
  44. extern    Boolean        noRedrawGrph;
  45.  
  46. extern    int            graphType;
  47.  
  48. extern    Vector        maxVect, minVect;
  49.  
  50. extern    Real        rotMatrx[3][3];
  51. extern    Boolean        inMultiFndr;
  52.  
  53.  
  54. Real        TheFunction(...);
  55. Boolean        CmndPeriod(...);
  56.  
  57.  
  58. /***        Local variables        ***/
  59. Real    startX, startY;
  60. Real    endX, endY;
  61. Real    deltaX, deltaY;
  62. int        numX, numY;
  63.  
  64.  
  65. Boolean        invldFormla;
  66. static    int        *texasPtr;
  67.  
  68. static    int lastOp = END_OP;
  69.  
  70. /***        Local functions        ***/
  71.  
  72. void    ToUprStr(...);
  73.  
  74.  
  75. EvalFunction()
  76. {
  77.     Boolean    AllocatePts();
  78.  
  79.     invldFormla = FALSE;
  80.     noRedrawGrph = TRUE;
  81.  
  82.     if (graphType EQ FUNCT_GTYPE)
  83.         LoadFunction();
  84.     else
  85.         LoadDeriv();
  86.  
  87.     if (invldFormla)    /* already gave warning message */
  88.         return;
  89.  
  90.     GetSpecDCont();
  91.  
  92.     deltaX = (endX - startX) / (numX - 1);
  93.     deltaY = (endY - startY) / (numY - 1);
  94.  
  95.     if (NOT(AllocatePts()))
  96.     {
  97.         MemAlert();
  98.         return;
  99.     }
  100.  
  101.     if (graphType EQ FUNCT_GTYPE)
  102.         StoreFunction();
  103.     else
  104.         StoreDeriv();
  105.  
  106.     vectrsCurrent = FALSE;
  107.     functCurrent = TRUE;
  108.     noRedrawGrph = FALSE;
  109. }
  110.  
  111.  
  112. LoadFunction()
  113. {
  114.     char    contStr[256];
  115.     int        itemType;
  116.     Handle    itemHndle;
  117.     Rect    itemRect;
  118.  
  119.     useMainFunc = TRUE;
  120.     GetDItem(functDial, DIALI_F_FUNCT, &itemType, &itemHndle, &itemRect);
  121.     GetIText(itemHndle, contStr);
  122.     ptoc(contStr);
  123.     ReadFormula(contStr);
  124. }
  125.  
  126. static
  127. ReadFormula(argStr)
  128. char    *argStr;
  129. {
  130.     int    op, lenOp;
  131.     Boolean    done = FALSE;
  132.     char    *strPtr;
  133.     int        lenStr;
  134.     int        texas[50];
  135.  
  136.     ToUprStr(argStr);
  137.     if (useMainFunc)
  138.     {
  139.         numMnOps = 0;
  140.         numMnConsts = 0;
  141.     }
  142.     else
  143.     {
  144.         numDerivOps = 0;
  145.         numDerivConsts = 0;
  146.     }
  147.  
  148.     texasPtr = texas + 49;
  149.     *texasPtr = END_SYMB;
  150.  
  151.     lenStr = strlen(argStr);
  152.     strPtr = argStr;
  153.  
  154.     invldFormla = FALSE;
  155.     lastOp = END_OP;
  156.  
  157.     while (NOT(done))
  158.     {
  159.         while(isspace(*strPtr))
  160.             ++strPtr;
  161.  
  162.         if (strPtr - argStr EQ lenStr)
  163.         {
  164.             op = END_SYMB;
  165.             lenOp = 0;
  166.         }
  167.         else
  168.             NextOp(strPtr, &op, &lenOp);
  169.         DoAction(op, lenOp, &done, &strPtr);
  170.     }
  171.     if (invldFormla)
  172.     {
  173.         Alert(ALRT_FORM, NIL);
  174.         if (useMainFunc)
  175.             numMnOps = 0;
  176.         else
  177.             numDerivOps = 0;
  178.     }
  179. }
  180.  
  181. static
  182. void
  183. ToUprStr(str)
  184. register    unsigned char    *str;
  185. {
  186. register    unsigned char c;
  187.  
  188.     c = *str;
  189.     while (c)
  190.     {
  191.         if ((*str >= 'a') AND (*str <= 'z'))
  192.             *str -= 'a' - 'A';
  193.         c = *(++str);
  194.     }
  195. }
  196.  
  197. static
  198. NextOp(argStr, op, lenOp)
  199. char    *argStr;
  200. int    *op, *lenOp;
  201. {
  202.     int    FindFunc(), LenNum();
  203.  
  204.     *lenOp = 1;
  205.     if (isdigit(argStr[0]) OR (argStr[0] EQ '.'))
  206.     {
  207.         *op = PUSH_NUM_OP;
  208.         *lenOp = LenNum(argStr);
  209.         return;
  210.     }
  211.  
  212.     switch (argStr[0]) {
  213.     case 'X':
  214.         *op = PUSH_X_OP;
  215.         break;
  216.     case 'Y':
  217.         *op = PUSH_Y_OP;
  218.         break;
  219.     case 'Z':
  220.         if (graphType EQ DERIV_GTYPE)
  221.             *op = PUSH_Z_OP;
  222.         else
  223.             invldFormla = TRUE;
  224.         break;
  225.     case 'R':
  226.         if (graphType EQ CYLIND_GTYPE)
  227.             *op = PUSH_X_OP;
  228.         else
  229.             invldFormla = TRUE;
  230.         break;
  231.     case 'P':
  232.         if (graphType EQ CYLIND_GTYPE)
  233.             *op = PUSH_Y_OP;
  234.         else
  235.             invldFormla = TRUE;
  236.         break;
  237.     case '+':
  238.         *op = ADD_OP;
  239.         break;
  240.     case '-':
  241.         *op = SUBT_OP;
  242.         break;
  243.     case '*':
  244.         *op = MULT_OP;
  245.         break;
  246.     case '/':
  247.         *op = DIV_OP;
  248.         break;
  249.     case '^':
  250.         *op = POWER_OP;
  251.         break;
  252.     case '(':
  253.         *op = OP_L_PAREN;
  254.         break;
  255.     case ')':
  256.         *op = OP_R_PAREN;
  257.         break;
  258.     default:
  259.         *op = FindFunc(argStr, lenOp);
  260.     }
  261. }
  262.  
  263. static
  264. int
  265. FindFunc(funcStr, lenFunc)
  266. register    char    *funcStr;
  267. int            *lenFunc;
  268. {
  269.     if (NOT(strncmp(funcStr, "EXP", 3))) {
  270.         *lenFunc = 3;
  271.         return(EXP_OP);
  272.     }
  273.     if (NOT(strncmp(funcStr, "LOG", 3))) {
  274.         *lenFunc = 3;
  275.         return(LOG_OP);
  276.     }
  277.     if (NOT(strncmp(funcStr, "LOG10", 5))) {
  278.         *lenFunc = 5;
  279.         return(LOG10_OP);
  280.     }
  281.     if (NOT(strncmp(funcStr, "SQRT", 4))) {
  282.         *lenFunc = 4;
  283.         return(SQRT_OP);
  284.     }
  285.     if (NOT(strncmp(funcStr, "SQ", 2))) {
  286.         *lenFunc = 2;
  287.         return(SQ_OP);
  288.     }
  289.     if (NOT(strncmp(funcStr, "SINH", 4))) {
  290.         *lenFunc = 4;
  291.         return(SINH_OP);
  292.     }
  293.     if (NOT(strncmp(funcStr, "COSH", 4))) {
  294.         *lenFunc = 4;
  295.         return(COSH_OP);
  296.     }
  297.     if (NOT(strncmp(funcStr, "TANH", 4))) {
  298.         *lenFunc = 4;
  299.         return(TANH_OP);
  300.     }
  301.     if (NOT(strncmp(funcStr, "SIN", (long)3))) {
  302.         *lenFunc = 3;
  303.         return(SIN_OP);
  304.     }
  305.     if (NOT(strncmp(funcStr, "ASIN", 4))) {
  306.         *lenFunc = 4;
  307.         return(ASIN_OP);
  308.     }
  309.     if (NOT(strncmp(funcStr, "COS", 3))) {
  310.         *lenFunc = 3;
  311.         return(COS_OP);
  312.     }
  313.     if (NOT(strncmp(funcStr, "ACOS", 4))) {
  314.         *lenFunc = 4;
  315.         return(ACOS_OP);
  316.     }
  317.     if (NOT(strncmp(funcStr, "TAN", 3))) {
  318.         *lenFunc = 3;
  319.         return(TAN_OP);
  320.     }
  321.     if (NOT(strncmp(funcStr, "ATAN", 4))) {
  322.         *lenFunc = 4;
  323.         return(ATAN_OP);
  324.     }
  325.     if (NOT(strncmp(funcStr, "COTAN", 5))) {
  326.         *lenFunc = 5;
  327.         return(COTAN_OP);
  328.     }
  329.     invldFormla = TRUE;
  330. }
  331.  
  332. static
  333. int
  334. LenNum(argStr)
  335. register    char    *argStr;
  336. {
  337. register    char    *tstr;
  338.  
  339.     tstr = argStr;
  340.  
  341.     while(isdigit(*tstr))
  342.         ++tstr;
  343.  
  344.     if (*tstr EQ '.')
  345.     {
  346.         ++tstr;
  347.         while(isdigit(*tstr))
  348.             ++tstr;
  349.     }
  350.  
  351.     if ((*tstr EQ 'e') OR (*tstr EQ 'E'))
  352.     {
  353.         ++tstr;
  354.         if ((*tstr = '+') OR (*tstr = '-'))
  355.             ++tstr;
  356.         while(isdigit(*tstr))
  357.             ++tstr;
  358.     }
  359.     return((int)(tstr - argStr));
  360. }
  361.  
  362.  
  363. #define    CMP_NONE    0
  364. #define    CMP_SIGN    1
  365. #define    CMP_HALT    2
  366. #define    CMP_ERROR    3
  367.  
  368.  
  369. static
  370. DoAction(op, lenOp, done, argStr)
  371. int        op;
  372. int        lenOp;
  373. Boolean *done;
  374. char    **argStr;
  375. {
  376.     int        action, localOp;
  377.     Boolean    popOp;
  378.     int        CheckSymbs();
  379.  
  380.     localOp = op;
  381.  
  382.     action = CheckSymbs(&localOp, done);
  383.  
  384.     switch (action) {
  385.     case ACT_OPtTEX:    /* send it to texas */
  386.         --texasPtr;
  387.         *texasPtr = localOp;
  388.         popOp = TRUE;
  389.         break;
  390.     case ACT_TEXtF:        /* pop from texas to formula */
  391.         PushOpFormula(*texasPtr++);
  392.         popOp = FALSE;
  393.         break;
  394.     case ACT_DELOPT:    /* send it to texas */
  395.         ++texasPtr;
  396.         popOp = TRUE;
  397.         break;
  398.     case ACT_STPDN:        /* we're done */
  399.         *done = TRUE;
  400.         popOp = FALSE;
  401.         break;
  402.     case ACT_STPERR:    /* something wrong; stop */
  403.         invldFormla = TRUE;
  404.         *done = TRUE;
  405.         popOp = FALSE;
  406.         break;
  407.     case ACT_OPtF:    /* add it to the formula */
  408.         PushOpFormula(localOp);
  409.         popOp = TRUE;
  410.         if (localOp EQ PUSH_NUM_OP)
  411.             PushConst(*argStr);
  412.         break;
  413.     case ACT_DELOP:    /* get rid of it */
  414.         popOp = TRUE;
  415.         break;
  416.     }
  417.  
  418.     if (popOp)
  419.         *argStr += lenOp;
  420. }
  421.  
  422. static
  423. PushOpFormula(newOp)
  424. int    newOp;
  425. {
  426.     if (useMainFunc)
  427.     {
  428.         mainFunct[numMnOps] = newOp;
  429.         ++numMnOps;
  430. /*        if (numMnOps > MAX_OPS)
  431.             GeneralAlert("Formula too complex");
  432. */
  433.     }
  434.     else
  435.     {
  436.         derivFunct[numDerivOps] = newOp;
  437.         ++numDerivOps;
  438.     }
  439. }
  440.  
  441. static
  442. PushConst(constStr)
  443. char    *constStr;
  444. {
  445.     Real    atof();
  446.  
  447.     if (useMainFunc)
  448.         mnConsts[numMnConsts++] = atof(constStr);
  449.     else
  450.         derivConsts[numDerivConsts++] = atof(constStr);
  451. }
  452.  
  453. static
  454. int
  455. CheckSymbs(op, done)
  456. int        *op;
  457. Boolean    *done;
  458. {
  459.  
  460.  
  461. static    int        actionTable[MAX_SYMBS][MAX_SYMBS] = {
  462.                         /* next symb -> */
  463.         /* texas V */
  464.                         4,1,1,1,1,1,1,5,1,6,1,
  465.                         2,2,2,1,1,1,1,2,1,6,1,
  466.                         2,2,2,1,1,1,1,2,1,6,1,
  467.                         2,2,2,2,2,1,1,2,1,6,1,
  468.                         2,2,2,2,2,1,1,2,1,6,1,
  469.                         2,2,2,2,2,2,1,2,1,6,1,
  470.                         5,1,1,1,1,1,1,3,1,6,1,
  471.                         5,5,5,5,5,5,5,5,1,5,1,
  472.                         2,2,2,2,2,2,1,2,5,5,1,
  473.                         5,5,5,5,5,5,5,5,5,5,1,
  474.                         2,2,2,2,2,2,1,2,1,6,1
  475.                         };
  476.  
  477.  
  478. static    int        compareOps[MAX_SYMBS][MAX_SYMBS] = {
  479. /*curr op -> */
  480. /*last op V */
  481. CMP_HALT,  CMP_SIGN,  CMP_SIGN,  CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_NONE,  CMP_ERROR, CMP_NONE,  CMP_NONE,  CMP_NONE,
  482. CMP_ERROR, CMP_SIGN,  CMP_SIGN,  CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_NONE,  CMP_ERROR, CMP_NONE,  CMP_NONE,  CMP_NONE,
  483. CMP_ERROR, CMP_SIGN,  CMP_SIGN,  CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_NONE,  CMP_ERROR, CMP_NONE,  CMP_NONE,  CMP_NONE,
  484. CMP_ERROR, CMP_SIGN,  CMP_SIGN,  CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_NONE,  CMP_ERROR, CMP_NONE,  CMP_NONE,  CMP_NONE,
  485. CMP_ERROR, CMP_SIGN,  CMP_SIGN,  CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_NONE,  CMP_ERROR, CMP_NONE,  CMP_NONE,  CMP_NONE,
  486. CMP_ERROR, CMP_SIGN,  CMP_SIGN,  CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_NONE/*CMP_ERROR*/, CMP_ERROR, CMP_NONE,  CMP_NONE,  CMP_NONE,
  487. CMP_ERROR, CMP_SIGN,  CMP_SIGN,  CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_NONE,  CMP_ERROR, CMP_NONE,  CMP_NONE,  CMP_NONE,
  488. CMP_NONE,  CMP_NONE,  CMP_NONE,  CMP_NONE,  CMP_NONE,  CMP_NONE,  CMP_ERROR, CMP_NONE,  CMP_ERROR, CMP_ERROR, CMP_NONE,
  489. CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_NONE,  CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_NONE,
  490. CMP_NONE,  CMP_NONE,  CMP_NONE,  CMP_NONE,  CMP_NONE,  CMP_NONE,  CMP_ERROR, CMP_NONE,  CMP_ERROR, CMP_ERROR, CMP_NONE,
  491. CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_NONE,  CMP_ERROR, CMP_NONE,  CMP_NONE,  CMP_NONE
  492. };
  493.  
  494.     int    errCode, symbol, action;
  495.  
  496.  
  497.     symbol = SymbFromOp(*op);
  498.  
  499.     action = actionTable[SymbFromOp(*texasPtr)][symbol];
  500.  
  501.     errCode = compareOps[SymbFromOp(lastOp)][SymbFromOp(*op)];
  502.  
  503.     switch (errCode) {
  504.     case CMP_NONE:
  505.         break;
  506.     case CMP_SIGN:
  507.         if (*op EQ SUBT_OP)
  508.             *op = NEG_OP;
  509.         else
  510.             action = ACT_DELOP;
  511.         action = actionTable[SymbFromOp(*texasPtr)][SymbFromOp(*op)];
  512.         break;
  513.     case CMP_HALT:
  514.         *done = TRUE;
  515.         break;
  516.     case CMP_ERROR:
  517.         *done = TRUE;
  518.         invldFormla = TRUE;
  519.         break;
  520.     default:
  521.         *done = TRUE;
  522.     }
  523.  
  524.     if ((action NEQ ACT_DELOP) AND (action NEQ ACT_TEXtF))
  525.         lastOp = *op;
  526.  
  527.     return(action);
  528. }
  529.  
  530. static
  531. int
  532. SymbFromOp(op)
  533. int    op;
  534. {
  535.     if (op < 0) {
  536.         if (op > OP_L_PAREN)
  537.             return(NUMB_SYMB);
  538.         if (op EQ OP_L_PAREN)
  539.             return(L_PAREN_SYMB);
  540.         return(R_PAREN_SYMB);
  541.     }
  542.  
  543.     if (op EQ END_OP)
  544.         return(END_SYMB);
  545.  
  546.     if (op <= POWER_OP)
  547.         return(op);
  548.  
  549.     if (op EQ NEG_OP)
  550.         return(NEG_SYMB);
  551.     else if (op > NEG_OP)
  552.         return(FUNC_SYMB);
  553.     
  554.     return(END_SYMB);
  555. }
  556.  
  557. static
  558. LoadDeriv()
  559. {
  560.     char    contStr[256];
  561.     int        itemType;
  562.     Handle    itemHndle;
  563.     Rect    itemRect;
  564.  
  565.     useMainFunc = TRUE;
  566.     GetDItem(functDial, DIALI_D_FUNC1, &itemType, &itemHndle, &itemRect);
  567.     GetIText(itemHndle, contStr);
  568.     ptoc(contStr);
  569.     ReadFormula(contStr);
  570.  
  571.     useMainFunc = FALSE;
  572.     GetDItem(functDial, DIALI_D_FUNC2, &itemType, &itemHndle, &itemRect);
  573.     GetIText(itemHndle, contStr);
  574.     ptoc(contStr);
  575.     ReadFormula(contStr);
  576. }
  577.  
  578. Boolean
  579. AllocatePts()
  580. {
  581.     if (funcResults NEQ NIL)
  582.         free(funcResults);
  583.     if (scalVectResults NEQ NIL)
  584.         free((void *)scalVectResults);
  585.     if (graphPoints NEQ NIL)
  586.         free((void *)graphPoints);
  587.     funcResults = (Real *)NewPtr((long)sizeof(Real) * (long)numX * numY);
  588.     if (MemErr)
  589.         goto Fail;
  590.     scalVectResults = (Vector *)NewPtr((long)sizeof(Vector) * (long)numX * numY);
  591.     if (MemErr)
  592.         goto Fail;
  593.     graphPoints = (Point *)NewPtr((long)sizeof(Point) * (long)numX * numY);
  594.     if (MemErr)
  595.         goto Fail;
  596.  
  597.     return(TRUE);
  598. Fail:
  599.     InitPts();
  600.     return(FALSE);
  601. }
  602.  
  603. MemAlert()
  604. {
  605.     InitCursor();
  606.     Alert(ALRT_MEMRY, NIL);
  607. }
  608.  
  609. static
  610. StoreFunction()
  611. {
  612.     register    int    xCnt, yCnt;
  613.     Real        currX, currY;
  614.     Real        maxFunc, minFunc, funcVal;
  615.     Real        xAtMax, yAtMax;
  616.     Real        xAtMin, yAtMin;
  617.     
  618.     ShowMeter((long)numX * numY);
  619.  
  620.     useMainFunc = TRUE;
  621.     funcVal = TheFunction(startX, startY);
  622.     maxFunc = funcVal;
  623.     minFunc = funcVal;
  624.     xAtMax = startX;
  625.     yAtMax = startY;
  626.     xAtMin = startX;
  627.     yAtMin = startY;
  628.  
  629.     currX = startX;
  630.     for (xCnt = 0; xCnt < numX; xCnt++)
  631.     {
  632.         currY = startY;
  633.         for (yCnt = 0; yCnt < numY; yCnt++)
  634.         {
  635.             funcVal = TheFunction(currX, currY);
  636.             DisplayMeter();
  637.             funcResults[(long)xCnt * (long)numY + yCnt] = funcVal;
  638.             if (funcVal > maxFunc)
  639.             {
  640.                 maxFunc = funcVal;
  641.                 xAtMax = currX;
  642.                 yAtMax = currY;
  643.             }
  644.             else if (funcVal < minFunc)
  645.             {
  646.                 minFunc = funcVal;
  647.                 xAtMin = currX;
  648.                 yAtMin = currY;
  649.             }
  650.             currY += deltaY;
  651.         }
  652.         if (CmndPeriod())
  653.             break;  /* for */
  654.         currX += deltaX;
  655.     }
  656.  
  657. done:
  658.     maxVect.x = xAtMax;
  659.     maxVect.y = yAtMax;
  660.     maxVect.z = maxFunc;
  661.     minVect.x = xAtMin;
  662.     minVect.y = yAtMin;
  663.     minVect.z = minFunc;
  664.  
  665.     RemoveMeter();
  666. }
  667.  
  668. static
  669. StoreDeriv()
  670. {
  671.     register    int    xCnt, yCnt;
  672.     Real        currFValX, currFValY;
  673.     Real        currX, currY, midXsqr, midYsqr;
  674.     Real        HlfDeltaX, HlfDeltaY;
  675.  
  676.     Real        maxFunc, minFunc;
  677.     Real        xAtMax, yAtMax;
  678.     Real        xAtMin, yAtMin;
  679.     Real        TheFunction(), GetInitVal();
  680.     Boolean        CmndPeriod();
  681.     
  682.     currFValX = GetInitVal();
  683.     ShowMeter((long)numX * numY);
  684.  
  685.     HlfDeltaX = deltaX / 2.0;
  686.     HlfDeltaY = deltaY / 2.0;
  687.  
  688.     maxFunc = currFValX;
  689.     minFunc = currFValX;
  690.     xAtMax = startX;
  691.     yAtMax = startY;
  692.     xAtMin = startX;
  693.     yAtMin = startY;
  694.  
  695.     currX = startX;
  696.     midXsqr = currX + HlfDeltaX;
  697.     for (xCnt = 0; xCnt < numX; xCnt++)
  698.     {
  699.         currFValY = currFValX;
  700.         currY = startY;
  701.         midYsqr = currY + HlfDeltaY;
  702.         useMainFunc = FALSE;    /* calculate dz/dy */
  703.         for (yCnt = 0; yCnt < numY; yCnt++)
  704.         {
  705.             DisplayMeter();
  706.             funcResults[xCnt * numY + yCnt] = currFValY;
  707.             if (currFValY > maxFunc)
  708.             {
  709.                 maxFunc = currFValY;
  710.                 xAtMax = currX;
  711.                 yAtMax = currY;
  712.             }
  713.             else if (currFValY < minFunc)
  714.             {
  715.                 minFunc = currFValY;
  716.                 xAtMin = currX;
  717.                 yAtMin = currY;
  718.             }
  719.             currFValY = currFValY +
  720.                     (TheFunction(currX, midYsqr, currFValY) * deltaY);
  721.             currY += deltaY;
  722.             midYsqr = currY + HlfDeltaY;
  723.         }
  724.         if (CmndPeriod())
  725.             break;  /* for */
  726.         useMainFunc = TRUE;    /* calculate dz/dx */
  727.         currFValX = currFValX +
  728.                     (TheFunction(midXsqr, startY, currFValX) * deltaX);
  729.         currX += deltaX;
  730.         midXsqr = currX + HlfDeltaX;
  731.     }
  732.  
  733.     maxVect.x = xAtMax;
  734.     maxVect.y = yAtMax;
  735.     maxVect.z = maxFunc;
  736.     minVect.x = xAtMin;
  737.     minVect.y = yAtMin;
  738.     minVect.z = minFunc;
  739.  
  740.     RemoveMeter();
  741. }
  742.  
  743. static
  744. Real
  745. GetInitVal()
  746. {
  747.     DialogRecord dStorage;
  748.     DialogPtr    initValDial;
  749.     int        itemSelected;
  750.     char    numStrX[100], numStrY[100];
  751.     Handle    itmHand, DialHandle();
  752.     double    atof();
  753. static    double    lastInitVal = 0.0;
  754.  
  755.     sprintf(numStrX, "%f", startX);
  756.     sprintf(numStrY, "%f", startY);
  757.     ctop(numStrX);
  758.     ctop(numStrY);
  759.     ParamText(numStrX, numStrY, "", "");
  760.  
  761.     initValDial = GetNewDialog(DIAL_INITVL, &dStorage, (DialogPtr)-1L);
  762.     itmHand = DialHandle(initValDial, DIALI_I_VALUE);
  763.     sprintf(numStrX, "%f", lastInitVal);
  764.     ctop(numStrX);
  765.     SetIText(itmHand, numStrX);
  766.  
  767.     ShowWindow(initValDial);
  768.  
  769.     InitCursor();
  770.     do {
  771.         ModalDialog(NIL, &itemSelected);
  772.     } while (itemSelected NEQ OK);
  773.     Clock();
  774.  
  775.     GetIText(itmHand, numStrX);
  776.     ptoc(numStrX);
  777.     CloseDialog(initValDial);
  778.  
  779.     lastInitVal = atof(numStrX);
  780.     return(lastInitVal);
  781. }
  782.  
  783. Handle
  784. DialHandle(theDial, theItem)
  785. DialogPtr    theDial;
  786. int        theItem;
  787. {
  788.     int        itemTyp;
  789.     Handle    itmHand;
  790.     Rect    disp;
  791.  
  792.     GetDItem(theDial, theItem, &itemTyp, &itmHand, &disp);
  793.     return(itmHand);
  794. }
  795.